package com.atguigu.tingshu.album.service.impl;

import ch.qos.logback.classic.turbo.TurboFilter;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    /**
     * 保存声音
     *
     * @param trackInfoVo
     * @param userId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //创建对象
        try {
            TrackInfo trackInfo = new TrackInfo();

            //有相同属性的拷贝
            BeanUtils.copyProperties(trackInfoVo, trackInfo);
            //userId赋值
            trackInfo.setUserId(userId);
            //查询对应的集数 +1
            AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
            //查询流媒体的数据，然后赋值，使用云点播的api
            TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //赋值
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            //保存声音结束
            trackInfoMapper.insert(trackInfo);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
            saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
            //	album_info; 更新数据;
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
            //	更新操作;
            albumInfoMapper.updateById(albumInfo);
        } catch (
                BeansException e) {
            log.error("保存声音信息失败：{}", e);
            throw new RuntimeException(e);
        }
    }

    public void saveTrackStat(Long trackId, String statPlay) {

        TrackStat trackStat = new TrackStat();
        //	赋值
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(1000));
        //	数据保存
        trackStatMapper.insert(trackStat);
    }

    /**
     * 分页查询声音列表
     *
     * @param trackInfoVoPage
     * @param trackInfoQuery
     * @return
     */
    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackInfoVoPage, TrackInfoQuery trackInfoQuery) {
        return trackInfoMapper.selectUserTrackPage(trackInfoVoPage, trackInfoQuery);

    }

    /**
     * 删除声音
     *
     * @param trackId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long trackId) {
        //查询当前对象
        TrackInfo trackInfo = this.getById(trackId);
        trackInfoMapper.deleteById(trackId);
        //查找标签状态并删除
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //获取声音所属的专辑id
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //删除数据时序号也应该 -1
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        //将专辑信息更新到数据库中
        albumInfoMapper.updateById(albumInfo);
        //重新管理一下
        trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //删除云点播中没有用的声音记录
        vodService.deleteMediaFile(trackInfo.getMediaFileId());
    }

    /**
     * 修改声音
     *
     * @param trackId
     * @param trackInfoVo
     */
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //先知道是谁修改的操作
        TrackInfo trackInfo = this.getById(trackId);
        //获取原始文件的Id
        String originMediaFileId = trackInfo.getMediaFileId();
        //属性赋值
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //判断声音是否被修改
        if (!originMediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //修改了声音
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //赋值最新的数据
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
            //	原有不要的话;
            vodService.deleteMediaFile(originMediaFileId);
        }
        this.updateById(trackInfo);

    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
        //先根据专辑列表获取到声音列表
        IPage<AlbumTrackListVo> albumTrackListVoIPage = trackInfoMapper.selectAlbumTrackList(albumTrackListVoPage,albumId);
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //判断是否登录
        if (null == userId){
            //没有登录，专辑付费时，除试听时全收费
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
                //免费试听多少集
                Integer tracksForFree = albumInfo.getTracksForFree();
                //除去免费试听都要收费
                albumTrackListVoIPage.getRecords().stream().filter(albumTrackListVo ->
                        albumTrackListVo.getOrderNum()>tracksForFree).forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        }else {
            //获取用户信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
            Assert.notNull(userInfoVoResult,"获取用户信息失败");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo,"获取用户信息失败");
            //声明一个变量，记录是否付费
            boolean iPaid = false;
            //判断专辑类型：vip免费
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())){
                //前提时用户是vip已过期
                if ((userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) || userInfoVo.getIsVip() == 0){
                    //需要付费
                    iPaid = true;
                }
            }else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())){
                //必须付费
                iPaid = true;
            }
            //判断需要付费的情况
            if (iPaid){
                //远程调用，需要知道用户买了哪些声音
                List<AlbumTrackListVo> albumTrackListVoList = albumTrackListVoIPage.getRecords().stream().filter(albumTrackListVo ->
                        albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                //这个是付费的声音
                List<Long> trackIdList = albumTrackListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                //获取用户购买的声音列表；如果用户购买了；将购买的声音Id与状态储存到map集合中，
                Result<Map<Long,Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId,trackIdList);
                Assert.notNull(mapResult,"查询用户购买声音失败");
                Map<Long, Integer> map = mapResult.getData();
                // trackId ，1 买过 track ，0 未买
                for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
                    albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 0);
                }
            }
        }
        return albumTrackListVoIPage;
    }

    @Override
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        //判断是否属于播放量
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())){
            //调用更新方法
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(),trackStatMqVo.getTrackId(),trackStatMqVo.getStatType());
            //更新专辑的播放量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(),trackStatMqVo.getTrackId(),SystemConstant.ALBUM_STAT_PLAY);
        }else if (SystemConstant.TRACK_STAT_COLLECT.equals(trackStatMqVo.getStatType())){
            //...
        }
    }

    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
         /*
        1.  从当前点击的声音开始，计算有多少需要付费的声音列表;
        2.  查询用户是否购买过当前专辑对应的声音，然后与1步骤进行过滤;
         */
        List<Map<String, Object>> list = new ArrayList<>();
        //获取对象
        TrackInfo trackInfo = this.getById(trackId);
        //获取当前声音Id的排序值
        Integer orderNum = trackInfo.getOrderNum();
        //获取到当前用户购买的声音列表
        Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(trackIdListResult,"获取用户购买声音列表失败");
        List<Long> trackIdList = trackIdListResult.getData();
        //从当前声音开始计算有多少需要付费的集合Id
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .gt(TrackInfo::getOrderNum, trackInfo.getOrderNum()));
        //两个集合去差值
        List<TrackInfo> paidTrackIdList = trackInfoList.stream().filter(trackInfoItem -> !trackIdList.contains(trackInfoItem.getId())).collect(Collectors.toList());
        //根据专辑Id获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //判断
        if (paidTrackIdList.size() >= 0){
            //显示本集
            HashMap<String, Object> map = new HashMap<>();
            map.put("name","本集");
            //每一集声音对应一个钱数
            map.put("price",albumInfo.getPrice());
            map.put("trackCount",0);
            //添加本集到集合
            list.add(map);
        }
        //后9集
        if (paidTrackIdList.size() >0 && paidTrackIdList.size()<=10){
            HashMap<String, Object> map = new HashMap<>();
            map.put("name","后" + paidTrackIdList.size() + "集");
            //每一集对应一个钱
            map.put("price",albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount",paidTrackIdList.size());
            list.add(map);
        }
        //后10集
        if (paidTrackIdList.size() > 10){
            //显示本集
            HashMap<String, Object> map = new HashMap<>();
            map.put("name","后10集");
            //每一集声音对应一个钱数
            map.put("price",albumInfo.getPrice().multiply(new BigDecimal("10")));
            map.put("trackCount",10);
            //添加本集到集合
            list.add(map);
        }
        //后10几集
        if (paidTrackIdList.size() > 10 && paidTrackIdList.size()<= 20){
            HashMap<String, Object> map = new HashMap<>();
            map.put("name","后" + paidTrackIdList.size() + "集");
            //每一集对应一个钱
            map.put("price",albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount",paidTrackIdList.size());
            list.add(map);
        }
        if (paidTrackIdList.size() > 20){
            //显示本集
            HashMap<String, Object> map = new HashMap<>();
            map.put("name","后20集");
            //每一集声音对应一个钱数
            map.put("price",albumInfo.getPrice().multiply(new BigDecimal("20")));
            map.put("trackCount",20);
            //添加本集到集合
            list.add(map);
        }
        return list;
    }

    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long userId, Long trackId, Integer trackCount) {
        //声明一个集合
        List<TrackInfo> trackInfoList = new ArrayList<>();
        //获取用户购买过的声音列表
        TrackInfo trackInfo = this.getById(trackId);
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        //判断返回数据集
        Assert.notNull(userPaidTrackList,"查询用户购买的声音列表失败");
        List<Long> userPaidTrackIdList = userPaidTrackList.getData();

        //判断当前购买的集数
        if ( 0 == trackCount){
            //购买的是本集
            trackInfoList.add(trackInfo);
        }else {
            //设置查询条件
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.gt(TrackInfo::getOrderNum,trackInfo.getOrderNum())
                    .eq(TrackInfo::getAlbumId,trackInfo.getAlbumId());
            if (!CollectionUtils.isEmpty(userPaidTrackIdList)){
                //排除已购买的
                wrapper.notIn(TrackInfo::getId,userPaidTrackIdList);
            }
            wrapper.last(" LIMIT " + trackCount);
            //查询数据
            trackInfoList = trackInfoMapper.selectList(wrapper);
        }
        return trackInfoList;
    }

}
